#define MAX_SIZE 255

#include "stdio.h"
#include "stdlib.h"
#include "malloc.h"

#define TRUE 1
#define FALSE 0

#include "DataElement.h"
#include "SequenceList.h"

/**
 * InitList 初始化顺序表
 * @param seqList    要初始化的顺序表
 * @param elemArray  初始化时要添加的元素内容数组
 * @param length     初始化时添加的元素个数
*/
void InitList(SeqList *seqList, ElementType *elemArray, int length) {

    /**
     * 如果元素给叔大于最大容量，说明超出数组的最大容量,初始化失败
     */
    if (length > MAX_SIZE) {
        printf("超出了数组的最大容量,初始化失败!\n");
        return;
    }

    /* 初始化顺序表,并将初始长度置为 0 */
    seqList->length = 0;

    /*
     * 通过循环向顺序表的第 i 个位置插入元素 i
     * TODO: fix length-1 to length
     * */
    for (int i = 0; i < length; i++) {
        /* 调用插入操作: 向 seqList顺序表的第 i 个位置插入元素 i */
        InsertList(seqList, i, elemArray[i]);
    }

}

/**
 * InsertList           向顺序表中的 index 位置插入某个元素
 * @param seqList       要插入元素的顺序表
 * @param index         要插入的下标
 * @param element       要插入的元素
*/
void InsertList(SeqList *seqList, int index, ElementType element) {
    /**
     * 1. 验证插入后的元素空间是否超过 MAX_SIZE
     * 2. index 的值是否合法 [0,MAX_SIZE-1]
     * 3. 插入的 index 应该在 length 之内
     * 4. 从第 length-1个下标开始，前面一个元素赋值给后面一个元素
    */

    /* 如果顺序表的长度+1大于MAX_SIZE 说明顺序表已经满了,则插入元素失败 */
    if (seqList->length + 1 >= MAX_SIZE) {
        printf("顺序表已满,插入失败!\n");
        return;
    }
    /* 验证下标合法性 */
    if (index < 0 || index > MAX_SIZE - 1) {
        printf("只能在允许的下标范围内插入元素[0,%d]\n", MAX_SIZE - 1);
        return;
    }
    /* 验证 index 是否大于数组的长度 */
    if (index > seqList->length) {
        printf("插入的下标超过了数组的最大长度-1，插入失败!\n");
        return;
    }

    /**
     *  插入元素:
     *      i = seqList->length - 1 => 数组元素的最后一位
     *      i >= index => i 到 index 结束
     * */
    for (int i = seqList->length - 1; i >= index; i--) {
        /* 将数组的前一项元素赋值给数组元素的后一项 */
        seqList->elem[i + 1] = seqList->elem[i];
    }

    /* 将要插入的值赋值给第 index 个元素 */
    seqList->elem[index] = element;

    /* 顺序表的总长度+1 */
    seqList->length++;

    /* 由于传递的是指针,所以不需要返回,实际内容已经发生了更改  */
}

/**
 * PrintList         输出顺序表
 * @param seqList    要输出的顺序表
*/
void PrintList(SeqList *seqList) {
    for (int i = 0; i < seqList->length; i++) {
        printf("%d\t%s\n", seqList->elem[i].id, seqList->elem[i].name);
    }
}


/**
 * 删除顺序表中指定下标的元素
 * @param seqList   要操作的顺序表
 * @param index     删除顺序表中指定下标的元素
 * @return 返回删除的元素,如果删除失败, 返回 NULL TODO: return => 使用完毕后进行 free，否则会造成内存泄露
 */
ElementType *DeleteElement(SeqList *seqList, int index) {
    if (index < 0 || index > MAX_SIZE - 1) {
        printf("下标越界,无法删除指定下标的元素!s");
        return NULL;
    }
    /* 1. 找到要删除的元素,并保存起来以便于返回 (保存的是已删除元素的副本)*/
    ElementType *delElement = (ElementType *) malloc(sizeof(ElementType));
    /* 单独定义并调用查找函数,返回要删除元素的指针 */
    *delElement = *GetElement(seqList, index);
    /* 2. 从指定位置删除,后面一个元素赋值给前面一个元素 */
    for (int i = 0; i < seqList->length - 1; i++) {
        /* 后一项元素的值赋值给前一项 */
        seqList->elem[i] = seqList->elem[i + 1];
    }
    /* 3. 顺序表的总长度 -1 */
    seqList->length--;
    /* 使用完毕后进行 free，否则会造成内存泄露 */
    return delElement;
}

/**
 * 查找循序表中指定下标的元素
 * @param seqList 要操作的顺序表
 * @param index 查找顺序表中指定下标的元素
 * @return 返回要查找的元素,如果查找失败,返回 NULL
 */
ElementType *GetElement(SeqList *seqList, int index) {
    if (index < 0 || index > MAX_SIZE - 1) {
        printf("下标越界,无法找到指定下标的元素!s");
        return NULL;
    }
    /* 存储要查找的元素 */
    ElementType *element;
    element = &seqList->elem[index];

    return element;
}


/**
 * 获取顺序表的长度
 * @param seqList  要操作的顺序表
 * @return 返回长度
 */
int GetLength(SeqList *seqList) {
    /* 如果顺序表为空 返回顺序表长度为 0 */
    if (seqList == NULL) {
        return 0;
    }

    return seqList->length;
}

/**
 * 判断顺序表是否为空
 * @param seqList  要判断的顺序表
 * @return 为空返回 True 否则返回 False
 */
int IsEmpty(SeqList *seqList) {
    /* 如果顺序表为空返回 TRUE，否则返回 FALSE */
    return GetLength(seqList) == 0 ? TRUE : FALSE;
}

/**
 * 清空顺序表操作
 * @param seqList  要清空的顺序表
 */
void ClearList(SeqList *seqList) {
    /* 如果顺序表为空 终止 */
    if (seqList == NULL) {
        return;
    }
    /* 清空顺序表 */
    seqList->length = 0;
}